package com.csun.cmny.provider.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.config.properties.CmnyProperties;
import com.csun.cmny.provider.model.domain.*;
import com.csun.cmny.provider.model.dto.wechat.BindMobileDto;
import com.csun.cmny.provider.model.enums.UacEmpStatusEnum;
import com.csun.cmny.provider.model.enums.UacUserSourceEnum;
import com.csun.cmny.provider.model.enums.UacUserTypeEnum;
import com.csun.cmny.provider.model.exceptions.UacBizException;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.provider.utils.WeChatUtil;
import com.csun.cmny.provider.utils.WxUtils;
import com.csun.cmny.util.PublicUtil;
import com.csun.cmny.util.RedisKeyUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2021-01-19 10:17
 * @Description:
 */
@Slf4j
@Service
public class WeiXinServiceImpl implements WeiXinService {

    @Resource
    private CmnyProperties cmnyProperties;
    @Resource
    private UacOpenUserService uacOpenUserService;
    @Resource
    private UacUserService uacUserService;
    @Resource
    private UacGroupService uacGroupService;
    @Resource
    private UacGroupUserService uacGroupUserService;
    @Resource
    private UacRoleService uacRoleService;
    @Resource
    private UacRoleUserService uacRoleUserService;
    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    /**
     * 服务人员小程序
     */
    private static final String staff_appid = "wx03afc063aeb287df";
    private static final String staff_secret = "d86480de13d8f48edd6b3462116ed8bb";
    /**
     * 志愿者小程序
     */
    private static final String volunteer_appid = "wxd552bd3e477cc962";
    private static final String volunteer_secret = "f04030f6e486b844a7e0517aea85f8c6";

    /**
     * 登录
     */
    static final String LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session"
            + "?appid=%s"
            + "&secret=%s"
            + "&js_code=%s"
            + "&grant_type=authorization_code";;

    /**
     * 微信小程序登录
     *
     * @param code     the application
     * @param code     the code
     * @param nickName the nick name
     * @param avatar   the avatar url
     * @param gender   the gender
     * @param city     the city
     *
     * @return the uac user
     */
    @Override
    public UacUser login(String application, String code, String nickName, String avatar, String gender, String city) {

        if (PublicUtil.isEmpty(application)) {
            throw new BadCredentialsException("请填写应用名称");
        }

        // 分配角色
        String roleCode = "";
        String loginUrl = "";
        switch (application) {
            case "volunteer" :
                roleCode = "volunteer";
                loginUrl = String.format(LOGIN_URL, volunteer_appid, volunteer_secret, code);
                break;
            case "staff" :
                roleCode = "staff";
                loginUrl = String.format(LOGIN_URL, staff_appid, staff_secret, code);
                break;

            default:
                throw new BadCredentialsException("请填写正确应用名称");
        }

        // 发送请求，返回Json字符串
        String str = WeChatUtil.httpRequest(loginUrl, "GET", null);
        log.info("=====> wechat response [{}]", str);

        // 转成Json对象 获取openid
        JSONObject jsonObject = JSONObject.parseObject(str);

        // 我们需要的openid，在一个小程序中，openid是唯一的
        String openid = jsonObject.get("openid").toString();
        String session_key = jsonObject.get("session_key").toString();
        Object error_code = jsonObject.get("errcode");
        if (PublicUtil.isNotEmpty(error_code)) {
            int error = (int) error_code;
            if (error == 0) {
                throw new BadCredentialsException(jsonObject.get("errmsg").toString());
            }
        }

        UacOpenUser uacOpenUser = new UacOpenUser();
        uacOpenUser.setOpenId(openid);
        uacOpenUser = uacOpenUserService.selectOne(uacOpenUser);
        UacUser uacUser;
        if (PublicUtil.isEmpty(uacOpenUser)) {
            // 新增
            uacUser = new UacUser();
            uacUser.setUserName(nickName);
            uacUser.setSex(Integer.parseInt(gender));
            uacUser.setType(UacUserTypeEnum.OPERATE.getKey());
            uacUser.setUserSource(UacUserSourceEnum.INSERT.getKey());
            uacUser.setStatus(UacEmpStatusEnum.ENABLE.getType());
            uacUserService.save(uacUser);

            UacGroup uacGroup = new UacGroup();
            uacGroup.setGroupCode("root");
            uacGroup = uacGroupService.selectOne(uacGroup);

            UacGroupUser uacGroupUser = new UacGroupUser();
            uacGroupUser.setUserId(uacUser.getId());
            uacGroupUser.setGroupId(uacGroup.getId());
            uacGroupUserService.save(uacGroupUser);

            uacUser.setGroupId(uacGroup.getId());
            uacGroup.setGroupName(uacGroup.getGroupName());

            uacOpenUser = new UacOpenUser();
            uacOpenUser.setId(uacUser.getId());
            uacOpenUser.setAvatar(avatar);
            uacOpenUser.setCity(city);
            uacOpenUser.setAvatar(avatar);
            uacOpenUser.setNickName(nickName);
            uacOpenUser.setGender(gender);
            uacOpenUser.setOpenId(openid);
            uacOpenUser.setSessionKey(session_key);
            uacOpenUserService.save(uacOpenUser);



            // 分配角色
            UacRole uacRole = uacRoleService.findByRoleCode(roleCode);
            uacRoleUserService.saveRoleUser(uacUser.getId(), uacRole.getId());
        } else {
            // 更新
            uacOpenUser.setAvatar(avatar);
            uacOpenUser.setCity(city);
            uacOpenUser.setAvatar(avatar);
            uacOpenUser.setNickName(nickName);
            uacOpenUser.setGender(gender);
            uacOpenUser.setOpenId(openid);
            uacOpenUser.setSessionKey(session_key);
            uacOpenUserService.update(uacOpenUser);

            uacUser = uacUserService.findUserInfoByUserId(uacOpenUser.getId());
        }

        // 缓存 session_key
        redisTemplate.opsForValue().set(RedisKeyUtil.getWeiXinSessionKey(uacUser.getId().toString()), session_key);

        return uacUser;
    }

    /**
     * 绑定手机号
     *
     * @param bindMobileDto the bind mobile dto
     *
     * @return the int.
     */
    @Override
    public Integer bindMobile(BindMobileDto bindMobileDto, LoginAuthDto loginAuthDto) {

        String userId = loginAuthDto.getUserId().toString();
        String session_key = String.valueOf(redisTemplate.opsForValue().get(RedisKeyUtil.getWeiXinSessionKey(userId)));
        String encryptedData = bindMobileDto.getEncryptedData();
        String iv = bindMobileDto.getIv();

        try {
            String result = WxUtils.wxDecrypt(encryptedData, session_key, iv);
            log.info("====> wx decrypt result [{}]", result);
            JSONObject json = JSONObject.parseObject(result);
            if (json.containsKey("phoneNumber")) {
                String phone = json.getString("phoneNumber");

                if (StringUtils.isNotBlank(phone)) {
                    //保存号码
                    UacUser uacUser = new UacUser();
                    uacUser.setId(loginAuthDto.getUserId());
                    uacUser.setMobileNo(phone);
                    return uacUserService.updateUser(uacUser);
                }
            }
        } catch (Exception e) {
            throw new UacBizException(ErrorCodeEnum.UAC10015003);
        }

        return 0;
    }
}
